# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: xguo

import functools

import dateutil.parser

from pymongo import MongoClient
from datetime import timedelta


@functools.lru_cache(maxsize=1)
def get_old_mongodb():
  config = {
      'user': 'inkyu',
      'passwd': 'sTsEWVtexVZaSz$x',
      'dbname': 'coin_20190101',
      'host': 'coin-mongodb.corp.prestolabs.io',
  }
  url = 'mongodb://{user}:{passwd}@{host}/{dbname}'.format(**config)
  db = MongoClient(url).coin_20190101
  return db


@functools.lru_cache(maxsize=1)
def get_new_mongodb():
  config = {
      'user': 'candle_importer',
      'passwd': 'GAX#GfvX4G$!f%40vf',
      'dbname': 'candle_20190101',
      'host': 'coin-mongodb.corp.prestolabs.io',
  }
  url = 'mongodb://{user}:{passwd}@{host}/{dbname}'.format(**config)
  db = MongoClient(url).candle_20190101
  return db


@functools.lru_cache(maxsize=1)
def get_local_mongodb():
  db = MongoClient().migrate_candle_20190101
  return db


@functools.lru_cache(maxsize=1)
def get_local_mongodb2():
  db = MongoClient().migrate_candle_20190101_10min
  return db


@functools.lru_cache(maxsize=1)
def get_strategy_names():
  db = get_old_mongodb()
  strategy_names = sorted(db.list_collection_names())
  return strategy_names


def same_range(one, two):
  a = one.minute / 5
  return (two - one == timedelta(minutes=5)) and (a % 2 == 1)


def merge_two(one_data, two_data):
  new = {
      "_id": two_data['_id'],
      "revision": two_data['revision'],
      "timestamp": two_data['timestamp'],
      "payload": [],  #'old_data': [one_data, two_data],
  }

  for one, two in zip(one_data['payload'], two_data['payload']):
    data = {
        "open": one['open'],
        "close": two['close'],
        "high": max(one['high'], two['high']),
        "low": min(one['low'], two['low']),
        "volume": one['volume'] + two['volume'],
        "value": two['value'],
        "currency": one['currency']
    }
    new['payload'].append(data)
  return new


def clean_data(data):
  timeset = set()
  res = []
  for d in data:
    t = d['timestamp']
    if t in timeset:
      continue
    else:
      res.append(d)
      timeset.add(t)
  return res


def merge_data(data):
  res = []
  for d in data:
    if len(res) == 0:
      res.append(d)
    else:
      last = res[-1]
      if same_range(last['timestamp'], d['timestamp']):
        res[-1] = merge_two(last, d)
      else:
        res.append(d)
  return res


def check():
  db = get_local_mongodb()
  col_names = get_strategy_names()
  local_db = get_local_mongodb2()
  query = {'revision': '20181201'}
  for col in col_names:
    data = list(local_db[col].find(query).sort([('timestamp', 1)]))


def check_new():
  db = get_new_mongodb()
  col_names = get_strategy_names()
  for col in col_names:
    data = list(db[col].find().sort([('_id', 1)]))
    print(data[0]['timestamp'])


def check_revision():
  db = get_local_mongodb2()
  col_names = get_strategy_names()
  revset = set()
  for col in col_names:
    data = list(db[col].find().sort([('timestamp', 1)]))
    for d in data:
      revset.add(d['revision'])
  for n in revset:
    print(n)


def change_tm(data):
  for d in data:
    a = d['timestamp'].minute / 5
    if a % 2 == 1:
      d['timestamp'] += timedelta(minutes=5)


def main_rev(rev):
  db = get_local_mongodb()
  col_names = get_strategy_names()
  local_db = get_local_mongodb2()
  query = {'revision': str(rev)}
  for col in col_names:
    data = list(db[col].find(query).sort([('timestamp', 1)]))
    print((query))
    data = clean_data(data)
    if data:
      mdata = merge_data(data)
      change_tm(mdata)
      n = len(mdata)
      mdata = clean_data(mdata)
      m = len(mdata)
      assert n == m, (n, m)
      local_db[col].insert_many(mdata)


def main():
  rev = [
      20181201,
      20181218,
      20181219,
      20181220,
      20181229,
  ]
  for r in rev:
    main_rev(str(r))


def copy_to_prod():
  db = get_local_mongodb2()
  col_names = get_strategy_names()
  db2 = get_new_mongodb()
  for col in col_names:
    data = list(db2[col].find().sort([('timestamp', 1)]))
    if data:
      ts = data[0]['timestamp']
      query = {'timestamp': {'$lt': ts}}
      new_data = list(db[col].find(query))
      print(col, new_data[-1]['timestamp'])
    else:
      new_data = list(db[col].find())
      print(col, new_data[-1]['timestamp'])

    db2[col].insert_many(new_data)


check_new()
